package com.xframe.xdal.core.model;

import com.xframe.xdal.core.constant.ErrorCode;
import com.xframe.xdal.core.constant.ErrorMsg;
import com.xframe.xdal.core.domain.SysBaseEntity;
import com.xframe.xdal.core.exception.DalFrameException;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.model.mapping.TableInfoBuilder;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.AbstractCollection;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;

@Data
@Accessors(chain=true)
public class AKQueryModel {
    /**
     * 数据类型
     */
    private Class<?> dataType;
    /**
     * 表结构
     */
    private ITableInfo tableInfo;
    /**
     * 查询的值
     */
    private Collection<Object> akValues;
    /**
     * 引用关系列表
     */
    private String[] refNames;
    /**
     * AK名字
     */
    private String akName;


    public AKQueryModel setVal(Object...vals){
        if(akValues == null){
            akValues = new ArrayList();
        }
        for(Object val : vals){
            akValues.add(val);
        }
        return this;
    }

    public AKQueryModel cleanVal(){
        akValues = new ArrayList();
        return this;
    }


    /**
     * 适用单字段的唯一索引，根据唯一索引来查询一个完整的实体模型
     * @param dataType 查询的数据类型
     * @param tableInfo 表结构
     * @param codes 唯一键的值
     * @param refNames 引用关系列表
     * @return AKQueryModel 查询对象
     */
    public static AKQueryModel valueOf(Class<?> dataType,ITableInfo tableInfo,Collection<Object> codes,String... refNames){
        AKQueryModel akQueryModel = new AKQueryModel();
        akQueryModel.dataType = dataType;
        akQueryModel.akValues =codes;
        if(tableInfo == null){
            throw new DalFrameException(ErrorCode.TABLEINFO_NO_FIND, ErrorMsg.TABLEINFO_NO_FIND_MSG);
        }
        akQueryModel.tableInfo = tableInfo;
        akQueryModel.refNames = refNames;
        akQueryModel.akName = "";
        return akQueryModel;
    }

    /**
     * 适用单字段的唯一索引，根据唯一索引来查询一个完整的实体模型
     * @param dataType 查询的数据类型
     * @param tableInfo 表结构
     * @param code 唯一键的值
     * @param refNames 引用关系列表
     * @return AKQueryModel 查询对象
     */
    public static AKQueryModel valueOf(Class<?> dataType,ITableInfo tableInfo,Object code,String... refNames){
        AKQueryModel akQueryModel = new AKQueryModel();
        akQueryModel.dataType = dataType;
        akQueryModel.akValues = new ArrayDeque<>();
        akQueryModel.akValues.add(code);
        if(tableInfo == null){
            throw new DalFrameException(ErrorCode.TABLEINFO_NO_FIND, ErrorMsg.TABLEINFO_NO_FIND_MSG);
        }
        akQueryModel.tableInfo = tableInfo;
        akQueryModel.refNames = refNames;
        akQueryModel.akName = "";
        return akQueryModel;
    }

    /**
     * 适用单字段的唯一索引，根据唯一索引来查询一个完整的实体模型
     * @param dataType 查询的数据类型
     * @param code 关键字
     * @return AKQueryModel 查询对象
     */
    public static AKQueryModel valueOf(Class<?> dataType,Object code){
        return valueOf(dataType,code, SysBaseEntity.FULL_DATA);
    }
    /**
     * 适用单字段的唯一索引
     * @param dataType 查询的数据类型
     * @param akKey 关键字
     * @param refNames 引用关系
     * @return AKQueryModel 查询对象
     */
    public static AKQueryModel valueOf(Class<?> dataType,Object akKey,String... refNames){
        AKQueryModel akQueryModel = new AKQueryModel();
        akQueryModel.dataType = dataType;
        akQueryModel.akValues = new ArrayDeque<>();
        akQueryModel.akValues.add(akKey);
        ITableInfo tableInfo = TableInfoBuilder.BuildTableInfoByAnnotation(dataType);
        if(tableInfo == null){
            throw new DalFrameException(ErrorCode.TABLEINFO_NO_FIND, ErrorMsg.TABLEINFO_NO_FIND_MSG);
        }
        akQueryModel.tableInfo = tableInfo;
        akQueryModel.refNames = refNames;
        akQueryModel.akName = "";
        return akQueryModel;
    }

    /**
     * 根据类型来查询
     */
    public static AKQueryModel byType(Class<?> dataType,Collection<Object> akValues){
        AKQueryModel akQueryModel = new AKQueryModel();
        akQueryModel.dataType = dataType;
        akQueryModel.akValues = akValues;
        ITableInfo tableInfo = TableInfoBuilder.BuildTableInfoByAnnotation(dataType);
        if(tableInfo == null){
            throw new DalFrameException(ErrorCode.TABLEINFO_NO_FIND, ErrorMsg.TABLEINFO_NO_FIND_MSG);
        }
        akQueryModel.tableInfo = tableInfo;
        akQueryModel.refNames = new String[0];
        akQueryModel.akName = "";
        return akQueryModel;
    }
}
